Handhaving heeft de grootste invloed op misdaad#

Uitleg van perspectief + argumenten uit andere bronnen, redenering…

Met strengere straffen op illegale activiteiten worden deze minder aantrekkelijk voor potentiële misdadigers. Door de kans om gepakt te worden te vergroten en de gevolgen zwaarder te maken kan een land er voor zorgen dat de mogelijke winsten van misdaad de risico’s niet langer waard zijn, en mensen in plaats hiervan voor legale wegen kiezen om hun lot te verbeteren.

Volgens Petersen et al. (2023) zorgen door de politie geïnitieerde interventies bij voetgangersstops voor een 11% mindering in misdaad. Door deze stops worden misdaden tegen gehouden voordat ze gebeuren en zijn mensen minder geneigd om misdaden te plegen. Meer politie agenten betekent dat meer zulk soort stops kunnen zijn wat dan weer kan zorgen voor minder misdaden.

Armere landen ervaren minder misdaden doordat er meer politie agenten zijn#

blabla

Hide code cell source
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import numpy as np
import plotly.io as pio

pio.renderers.default = 'notebook'

# Load and process data
diefstallenbank1_df = pd.read_csv("world_bank_definitive.csv")
crime_df = pd.read_csv("europe_crime_definitive_per_100k.csv")

bank_df = diefstallenbank1_df[diefstallenbank1_df['Indicator Name'] == "GDP per capita, PPP (constant 2021 international $)"]
bank_df = bank_df.rename(columns={"Value": "GDP per capita, PPP (constant 2021 international $)"})

crime_columns = [col for col in crime_df.columns if col not in ["Country Name", "Year", "geo"]]
crime_df["Total Crime Rate per 100k"] = crime_df[crime_columns].sum(axis=1)

merged_df = pd.merge(
    crime_df[["Country Name", "Year", "Total Crime Rate per 100k"]],
    bank_df[["Country Name", "Year", "GDP per capita, PPP (constant 2021 international $)"]],
    on=["Country Name", "Year"]
)

# Prepare data for polynomial fit
x = merged_df["GDP per capita, PPP (constant 2021 international $)"]
y = merged_df["Total Crime Rate per 100k"]


# Drop rows with missing or infinite values
filtered_df = merged_df.replace([np.inf, -np.inf], np.nan).dropna(subset=[
    "GDP per capita, PPP (constant 2021 international $)", "Total Crime Rate per 100k"
])

x = filtered_df["GDP per capita, PPP (constant 2021 international $)"]
y = filtered_df["Total Crime Rate per 100k"]
# Fit a 2nd-degree polynomial (quadratic curve)
degree = 2  # you can change this to 3 for a cubic fit
coeffs = np.polyfit(x, y, deg=degree)
poly_func = np.poly1d(coeffs)

# Create x values for the trendline
x_vals = np.linspace(x.min(), x.max(), 500)
y_vals = poly_func(x_vals)

# Plot scatter with curved trendline
fig = px.scatter(
    merged_df,
    x="GDP per capita, PPP (constant 2021 international $)",
    y="Total Crime Rate per 100k",
    hover_name="Country Name",
    hover_data={"Year": True},
    title="GDP per Capita vs. Total Crime Rate per 100k with Curved Trendline"
)

# Add polynomial curve
fig.add_trace(go.Scatter(
    x=x_vals,
    y=y_vals,
    mode='lines',
    name=f'Polynomial Trendline (deg={degree})',
    line=dict(color='red', dash='dash')
))

fig.update_layout(
    xaxis_title="GDP per capita, PPP (constant 2021 international $)",
    yaxis_title="Total Crime Rate per 100k",
    showlegend=False
)


fig.show()

Figuur 3: Het GDP per capita in dollars vs het totaal aantal misdaden per land. Elk land is voor elk jaar dat het voorkomt in onze dataset weergegeven. Hover om de exacte waarden, het land en het jaar te zien van het datapunt

In figuur 3 is een algemeen positieve trend te zien tussen GDP per capita en de totale criminele activiteit. Dit lijkt te suggereren dat rijke landen meer te kampen hebben met illegale activiteiten dan minder welvarende.

Hide code cell source
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import numpy as np
import plotly.io as pio

pio.renderers.default = 'notebook'

# Load and process data
police_df = pd.read_csv("europe_justice_per_100k.csv")
crime_df = pd.read_csv("europe_crime_definitive_per_100k.csv")


crime_columns = [col for col in crime_df.columns if col not in ["Country Name", "Year", "geo"]]
crime_df["Total Crime Rate per 100k"] = crime_df[crime_columns].sum(axis=1)

merged_df = pd.merge(
    crime_df[["Country Name", "Year", "Total Crime Rate per 100k"]],
    police_df[["Country Name", "Year", "Police officers"]],
    on=["Country Name", "Year"]
)

# Prepare data for polynomial fit
x = merged_df["Police officers"]
y = merged_df["Total Crime Rate per 100k"]


# Drop rows with missing or infinite values
filtered_df = merged_df.replace([np.inf, -np.inf], np.nan).dropna(subset=[
    "Police officers", "Total Crime Rate per 100k"
])

x = filtered_df["Police officers"]
y = filtered_df["Total Crime Rate per 100k"]
# Fit a 2nd-degree polynomial (quadratic curve)
degree = 2  # you can change this to 3 for a cubic fit
coeffs = np.polyfit(x, y, deg=degree)
poly_func = np.poly1d(coeffs)

# Create x values for the trendline
x_vals = np.linspace(x.min(), x.max(), 500)
y_vals = poly_func(x_vals)

# Plot scatter with curved trendline
fig = px.scatter(
    merged_df,
    x="Police officers",
    y="Total Crime Rate per 100k",
    hover_name="Country Name",
    hover_data={"Year": True},
    title="Police officers vs. Total Crime Rate per 100k with Curved Trendline"
)

# Add polynomial curve
fig.add_trace(go.Scatter(
    x=x_vals,
    y=y_vals,
    mode='lines',
    name=f'Polynomial Trendline (deg={degree})',
    line=dict(color='red', dash='dash')
))

fig.update_layout(
    xaxis_title="Police officers",
    yaxis_title="Total Crime Rate per 100k",
    showlegend=False
)


fig.show()

Figuur bla

figuur hier onder kan weg?#

Hide code cell source
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.io as pio
import pycountry

pio.renderers.default = 'notebook'

# === Load Crime Data ===
theft_df = pd.read_csv("europe_crime_definitive_per_100k.csv")
theft_df.rename(columns={'geo': 'Country Code'}, inplace=True)
theft_columns = [col for col in theft_df.columns if col not in ["Country Name", "Year", "Country Code"]]
theft_df["Total Crime Rate per 100k"] = theft_df[theft_columns].sum(axis=1)

# === Load Police Data ===
police_df = pd.read_csv("europe_justice_per_100k.csv")
police_df.rename(columns={'geo': 'Country Code'}, inplace=True)

# Convert ISO-2 to ISO-3
def convert_iso2_to_iso3(code):
    try:
        return pycountry.countries.get(alpha_2=code).alpha_3
    except:
        return None

theft_df['Country Code'] = theft_df['Country Code'].apply(convert_iso2_to_iso3)
police_df['Country Code'] = police_df['Country Code'].apply(convert_iso2_to_iso3)

# Manual fixes for special regions/countries
manual_fix = {
    'England and Wales': 'GBR',
    'Northern Ireland (UK) (NUTS 2021)': 'GBR',
    'Scotland (NUTS 2021)': 'GBR',
    'Greece': 'GRC',
    'Kosovo*': 'XKX'
}



theft_df['Year'] = theft_df['Year'].astype(int)
theft_df['Total Crime Rate per 100k'] = pd.to_numeric(theft_df['Total Crime Rate per 100k'], errors='coerce').fillna(0)

# === Years intersection and max year 2022 ===
years = sorted(list(set(police_df['Year']).intersection(set(theft_df['Year']))))
years = [year for year in years if year <= 2022]

# Create subplot
fig = make_subplots(
    rows=1, cols=2,
    specs=[[{'type': 'choropleth'}, {'type': 'choropleth'}]],
    subplot_titles=('Crimes per 100k', 'Police per 100k')
)

# Define color scales
theft_min, theft_max = theft_df['Total Crime Rate per 100k'].min(), theft_df['Total Crime Rate per 100k'].max()
police_min, police_max = police_df['Police officers'].min(), police_df['Police officers'].max()


fig.add_trace(
    go.Choropleth(
        locations=theft_df[theft_df['Year'] == years[0]]['Country Code'],
        z=theft_df[theft_df['Year'] == years[0]]['Total Crime Rate per 100k'],
        text=theft_df[theft_df['Year'] == years[0]]['Country Name'],
        colorscale='Inferno',
        zmin=theft_min,
        zmax=theft_max,
        colorbar=dict(title='Total Crime Rate per 100k', x=0.45)  # position colorbar left
    ),
    row=1, col=1
)

fig.add_trace(
    go.Choropleth(
        locations=police_df[police_df['Year'] == years[0]]['Country Code'],
        z=police_df[police_df['Year'] == years[0]]['Police officers'],
        text=police_df[police_df['Year'] == years[0]]['Country Name'],
        colorscale='Purples',
        zmin=police_min,
        zmax=police_max,
        colorbar=dict(title='Police officers per 100k', x=1.0)  # position colorbar right
    ),
    row=1, col=2
)

# Animation frames
frames = []
for year in years:
    frame = go.Frame(
        data=[
            
            go.Choropleth(
                locations=theft_df[theft_df['Year'] == year]['Country Code'],
                z=theft_df[theft_df['Year'] == year]['Total Crime Rate per 100k'],
                text=theft_df[theft_df['Year'] == year]['Country Name']
            ),
            go.Choropleth(
                locations=police_df[police_df['Year'] == year]['Country Code'],
                z=police_df[police_df['Year'] == year]['Police officers'],
                text=police_df[police_df['Year'] == year]['Country Name']
            )
        ],
        name=str(year)
    )
    frames.append(frame)

# Update layout
fig.update_layout(
    title_text='Police officers and Total Crime per 100k in Europe per Year',
    title_x=0.5,
    geo=dict(
        showframe=False,
        showcoastlines=True,
        lataxis_range=[30, 72],
        lonaxis_range=[-25, 45],
        projection_type='natural earth'
    ),
    geo2=dict(  # for the 2nd map
        showframe=False,
        showcoastlines=True,
        lataxis_range=[30, 72],
        lonaxis_range=[-25, 45],
        projection_type='natural earth'
    ),
    sliders=[{
        "steps": [{
            "args": [[str(year)], {"frame": {"duration": 500, "redraw": True}, "mode": "immediate"}],
            "label": str(year),
            "method": "animate"
        } for year in years],
        "transition": {"duration": 300},
        "x": 0.1,
        "len": 0.8
    }],
    updatemenus=[{
        "buttons": [{
            "args": [None, {"frame": {"duration": 500, "redraw": True}, "fromcurrent": True}],
            "label": "Play",
            "method": "animate"
        }, {
            "args": [[None], {"frame": {"duration": 0}, "mode": "immediate"}],
            "label": "Pause",
            "method": "animate"
        }],
        "direction": "left",
        "pad": {"r": 10, "t": 70},
        "showactive": False,
        "type": "buttons",
        "x": 0.1,
        "xanchor": "right",
        "y": 0,
        "yanchor": "top"
    }]
)

fig.frames = frames

fig.show()

Figuur 4: twee kaarten met respectievelijk de GINI-coëfficient en de criminele activiteit per land.

In figuur 4 worden de Gini-coëfficient en de criminele activiteit per land over de jaren heen vergeleken. In deze figuur kunnen we zien dat de Gini-coëfficient en criminaliteit in ieder land onafhankelijk van elkaar bewegen. Het is daardoor onwaarschijnlijk dat de economische ongelijkheid en criminele activiteit significant verbonden zijn.

Argument 3: Meer politie in landen met lager GDP per capita#

Hoewel je zou verwachten dat armere landen minder geld hebben voor meer politie agenten, is dit niet altijd het geval. Omdat in arme landen eerder incentief kan onstaan om misdaden te plegen, kan het een goede preventieve maatregeling zijn om meer politie agenten in te schakelen. In deze grafiek zie je dat als onze data in vier gelijke delen opdeelt, dat er een trend in Europa is dat hoe hoger het GDP per capita is, hoe lager het aantal politieagenten per 100.000 man is.

Hide code cell source
import pandas as pd
import plotly.express as px
import plotly.io as pio

pio.renderers.default = 'notebook'

# Load data
bank1_df = pd.read_csv("world_bank_definitive.csv")
police_df = pd.read_csv("europe_justice_per_100k.csv")

# Filter GDP data
bank_df = bank1_df[bank1_df['Indicator Name'] == "GDP per capita, PPP (constant 2021 international $)"]
bank_df = bank_df.rename(columns={"Value": "GDP per capita, PPP (constant 2021 international $)"})

# Merge datasets
merged_df = pd.merge(
    police_df[["Country Name", "Year", "Police officers"]],
    bank_df[["Country Name", "Year", "GDP per capita, PPP (constant 2021 international $)"]],
    on=["Country Name", "Year"]
)

# Drop missing values
merged_df = merged_df.dropna()

# Compute quartiles with actual bin edges
gdp_series = merged_df["GDP per capita, PPP (constant 2021 international $)"]
quartiles, bins = pd.qcut(gdp_series, q=4, retbins=True, precision=0)

# Format bin labels with ranges
quartile_labels = [
    f"Q1: {int(bins[0]):,}{int(bins[1]):,}",
    f"Q2: {int(bins[1]+1):,}{int(bins[2]):,}",
    f"Q3: {int(bins[2]+1):,}{int(bins[3]):,}",
    f"Q4: {int(bins[3]+1):,}{int(bins[4]):,}"
]

# Assign quartile labels
merged_df['GDP Quartile'] = pd.qcut(
    gdp_series,
    q=4,
    labels=quartile_labels
)

# Define blue gradient colors
color_discrete_map = {
    quartile_labels[0]: "#03DBFC",  # Light blue
    quartile_labels[1]: "#00B4FF",
    quartile_labels[2]: "#006CFF",
    quartile_labels[3]: "#000FFF"   # Dark blue
}

# Create box plot with custom colors and ordered x-axis
fig = px.box(
    merged_df,
    x="GDP Quartile",
    y="Police officers",
    color="GDP Quartile",
    color_discrete_map=color_discrete_map,
    category_orders={"GDP Quartile": quartile_labels},
    title="Police Officers per 100k by GDP per Capita, for each quartile of the data",
    labels={"Police officers": "Police Officers per 100k", "GDP Quartile": "GDP per Capita Quartile"}
)

# Update layout to remove legend (since the x-axis already shows quartiles)
fig.update_layout(showlegend=False)

fig.show()

Hier zijn natuurlijk uitzonderingen op en het moet opgemerkt worden dat dit ook zou kunnen komen doordat specifieke landen een ander politiek beleid hebben waardoor er meer politie is (wat niet perse met welvaart te maken heeft). Maar dit geeft wel een mogelijke uitleg voor waarom er in armere landen minder misdaden plaatsvinden: namelijk dat er meer politie is om misdaden tegen te houden/af te schrikken. Je zou dus kunnen zeggen dat er minder misdaden in armere landen plaatsvinden tegenover rijkere landen, doordat armere landen meer politie hebben en door die politie onstaat minder misdaad.